<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-alpha.65">
<title data-react-helmet="true">14. 安全鉴权 | Fur</title><meta data-react-helmet="true" name="docsearch:version" content="current,latest"><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:title" content="14. 安全鉴权 | Fur"><meta data-react-helmet="true" name="description" content="14.1 什么是鉴权"><meta data-react-helmet="true" property="og:description" content="14.1 什么是鉴权"><meta data-react-helmet="true" property="og:url" content="https://furos.cn/docs/auth-control"><link data-react-helmet="true" rel="shortcut icon" href="/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://furos.cn/docs/auth-control"><link rel="stylesheet" href="/styles.8aef5b7b.css">
<link rel="preload" href="/styles.8352e18a.js" as="script">
<link rel="preload" href="/runtime~main.98e14d7d.js" as="script">
<link rel="preload" href="/main.04e1b7d6.js" as="script">
<link rel="preload" href="/1.72c59440.js" as="script">
<link rel="preload" href="/2.a2e0b0a9.js" as="script">
<link rel="preload" href="/3.054f69af.js" as="script">
<link rel="preload" href="/1be78505.da78ff7d.js" as="script">
<link rel="preload" href="/85.0018927c.js" as="script">
<link rel="preload" href="/f976f453.e1be0e0e.js" as="script">
<link rel="preload" href="/17896441.9aece880.js" as="script">
<link rel="preload" href="/904cf40b.dd7b9495.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<nav class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><div aria-label="Navigation bar toggle" class="navbar__toggle" role="button" tabindex="0"><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></div><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo.png" alt="Fur Logo"><strong class="navbar__title">Fur</strong></a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs/">Next</a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs">文档</a><a class="navbar__item navbar__link" href="/blog">博客</a><a href="https://chinadot.net" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">社区</a></div><div class="navbar__items navbar__items--right"><a href="https://space.bilibili.com/695987967" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">视频</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">工具</a><ul class="dropdown__menu"><li><a target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">代码生成器</a></li></ul></div><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">看板</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">仓库</a><ul class="dropdown__menu"><li><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">Gitee</a></li><li><a href="https://github.com/MonkSoul/Fur" target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">GitHub</a></li></ul></div><div class="react-toggle react-toggle--disabled displayOnlyInLargeViewport_2aTZ"><div class="react-toggle-track"><div class="react-toggle-track-check"><span class="toggle_BsTx">🌜</span></div><div class="react-toggle-track-x"><span class="toggle_BsTx">🌞</span></div></div><div class="react-toggle-thumb"></div><input type="checkbox" disabled="" aria-label="Dark mode toggle" class="react-toggle-screenreader-only"></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div><div class="navbar-sidebar"><div class="navbar-sidebar__brand"><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo.png" alt="Fur Logo"><strong class="navbar__title">Fur</strong></a></div><div class="navbar-sidebar__items"><div class="menu"><ul class="menu__list"><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link">Versions</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link navbar__link--active" href="/docs">文档</a></li><li class="menu__list-item"><a class="menu__link" href="/blog">博客</a></li><li class="menu__list-item"><a href="https://chinadot.net" target="_blank" rel="noopener noreferrer" class="menu__link">社区</a></li><li class="menu__list-item"><a href="https://space.bilibili.com/695987967" target="_blank" rel="noopener noreferrer" class="menu__link">视频</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link menu__link--sublist">工具</a><ul class="menu__list"><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link" position="left">代码生成器</a></li></ul></li><li class="menu__list-item"><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="menu__link">看板</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link menu__link--sublist">仓库</a><ul class="menu__list"><li class="menu__list-item"><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="menu__link" position="left">Gitee</a></li><li class="menu__list-item"><a href="https://github.com/MonkSoul/Fur" target="_blank" rel="noopener noreferrer" class="menu__link" position="left">GitHub</a></li></ul></li></ul></div></div></div></nav><div class="main-wrapper"><div class="docPage_2gpo"><div class="docSidebarContainer_3_JD" role="complementary"><div class="sidebar_2urC"><div class="menu menu--responsive menu_5FrY"><button aria-label="Open Menu" aria-haspopup="true" class="button button--secondary button--sm menu__button" type="button"><svg aria-label="Menu" class="sidebarMenuIcon_Dm3K" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 32 32" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><ul class="menu__list"><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">1. 框架介绍</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/">1.1 介绍</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/author">1.2 关于作者</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/source">1.3 源码结构</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/reference">1.4 项目引用</a></li></ul></li><li class="menu__list-item"><a class="menu__link" href="/docs/get-start">2. 一分钟入门</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/appstartup">3. 应用启动</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">4. 配置与选项</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/configuration">4.1 配置</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/options">4.2 选项</a></li></ul></li><li class="menu__list-item"><a class="menu__link" href="/docs/dynamic-api-controller">5. 动态 WebAPI</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/specification-document">6. 规范化接口文档</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/friendly-exception">7. 友好异常处理</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/data-validation">8. 数据校验</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">9. 数据库操作指南</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext">9.1 数据库上下文</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-locator">9.2 数据库上下文定位器</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/entity">9.3 数据库实体</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-repository">9.4 仓储模式</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-add">9.5 新增操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-update">9.6 更新操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-add-or-update">9.7 新增或更新操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-delete">9.8 删除操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-batch">9.9 批量操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-query">9.10 查询操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-hight-query">9.11 高级查询操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-view">9.12 视图操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-proc">9.13 存储过程操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-function">9.14 函数操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-sql">9.15 Sql 操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-sql-template">9.16 Sql 模板</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-sql-proxy">9.17 Sql 高级代理</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-multi-database">9.18 多数据库操作</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-db-first">9.19 数据库生成模型</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-code-first">9.20 模型生成数据库</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-seed-data">9.21 实体种子数据</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-audit">9.22 审计日志</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-filter">9.23 实体/全局查询筛选器</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-Interceptor">9.24 数据库操作拦截器</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/tran">9.25 事务和工作单元</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext-read-write">9.26 读写分离/主从复制</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/split-db">9.27 分表分库</a></li></ul></li><li class="menu__list-item"><a class="menu__link" href="/docs/saas">10. SaaS 多租户</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/dependency-injection">11. 依赖注入/控制反转</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/object-mapper">12. 对象数据映射</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/cache">13. 分布式缓存</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link menu__link--active active" href="/docs/auth-control">14. 安全鉴权</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/cors">15. CORS 跨域</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/view-engine">16. 视图引擎</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/local-language">17. 多语言处理</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/event-bus">18. 事件总线</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/logging">19. 日志记录</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/http">20. 网络请求</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/process-service">21. 进程服务</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/job">22. 任务调度</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/signalr">23. 即时通讯</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/grpc">24. Grpc 服务</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/deploy">25. 托管部署</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/devops">26. 持续部署集成</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">27. 测试指南</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/unittest">27.1 单元测试</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/performance">27.2 性能测试</a></li></ul></li><li class="menu__list-item"><a class="menu__link" href="/docs/contribute">28. 贡献指南</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">29. 常见问题</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/answer">29.1 常见问题</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/errors">29.2 常见错误</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/gooduse">29.3 最佳实践</a></li></ul></li></ul></div></div></div><main class="docMainContainer_3EyW"><div class="container padding-vert--lg docItemWrapper_1EkI"><div class="row"><div class="col docItemCol_2ASc"><div class="docItemContainer_3QWW"><article><header><h1 class="docTitle_1Lrw">14. 安全鉴权</h1></header><div class="markdown"><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="141-什么是鉴权"></a>14.1 什么是鉴权<a aria-hidden="true" tabindex="-1" class="hash-link" href="#141-什么是鉴权" title="Direct link to heading">#</a></h2><p><strong>鉴权实际上就是一种身份认证</strong>。</p><p>由用户提供凭据，然后将其与存储在操作系统、数据库、应用或资源中的凭据进行比较。 在授权过程中，如果凭据匹配，则用户身份验证成功，可执行已向其授权的操作。 授权指判断允许用户执行的操作的过程。
也可以将身份验证理解为进入空间（例如服务器、数据库、应用或资源）的一种方式，而授权是用户可以对该空间（服务器、数据库或应用）内的哪些对象执行哪些操作。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="1411-常见的鉴权方式"></a>14.1.1 常见的鉴权方式<a aria-hidden="true" tabindex="-1" class="hash-link" href="#1411-常见的鉴权方式" title="Direct link to heading">#</a></h3><ul><li><code>HTTP Basic Authentication</code></li></ul><p>这是 <code>HTTP</code> 协议实现的基本认证方式，我们在浏览网页时，从浏览器正上方弹出的对话框要求我们输入账号密码，正是使用了这种认证方式</p><ul><li><code>Session + Cookie</code></li></ul><p>利用服务器端的 session（会话）和浏览器端的 cookie 来实现前后端的认证，由于 http 请求时是无状态的，服务器正常情况下是不知道当前请求之前有没有来过，这个时候我们如果要记录状态，就需要在服务器端创建一个会话(seesion),将同一个客户端的请求都维护在各自得会会话中，每当请求到达服务器端的时候，先去查一下该客户端有没有在服务器端创建 seesion，如果有则已经认证成功了，否则就没有认证。</p><ul><li><code>Token</code></li></ul><p>客户端在首次登陆以后，服务端再次接收 <code>HTTP</code> 请求的时候，就只认 <code>Token</code> 了，请求只要每次把 <code>Token</code> 带上就行了，服务器端会拦截所有的请求，然后校验 <code>Token</code> 的合法性，合法就放行，不合法就返回 401（鉴权失败）</p><p><code>Token</code>验证比较灵活，适用于大部分场景。常用的 <code>Token</code> 鉴权方式的解决方案是 <code>JWT</code>，<code>JWT</code> 是通过对带有相关用户信息的进行加密，加密的方式比较灵活，可以根据需求具体设计。</p><ul><li><code>OAuth</code></li></ul><p>OAuth（开放授权）是一个开放标准，允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息，而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容，为了保护用户数据的安全和隐私，第三方网站访问用户数据前都需要显式的向用户征求授权。我们常见的提供 OAuth 认证服务的厂商有支付宝，QQ,微信。</p><p>OAuth 协议又有 1.0 和 2.0 两个版本。相比较 1.0 版，2.0 版整个授权验证流程更简单更安全，也是目前最主要的用户身份验证和授权方式。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="142-如何使用"></a>14.2 如何使用<a aria-hidden="true" tabindex="-1" class="hash-link" href="#142-如何使用" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="1421-添加-cookie-授权"></a>14.2.1 添加 <code>Cookie</code> 授权<a aria-hidden="true" tabindex="-1" class="hash-link" href="#1421-添加-cookie-授权" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">// Cookies单独授权</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, b =&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            b.LoginPath = &quot;/Home/Login&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        });</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="1422-添加-jwt-授权"></a>14.2.2 添加 <code>Jwt</code> 授权<a aria-hidden="true" tabindex="-1" class="hash-link" href="#1422-添加-jwt-授权" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">services.AddJwt();</span></div></div></div></div></div><div class="admonition admonition-important alert alert--info"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p><code>JWT</code> 鉴权并未包含在 <code>Fur</code> 框架中，需要安装 <code>Fur</code> 框架提供的 <code>Fur.Extras.Authentication.JwtBearer</code> 拓展包。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="1423-混合授权"></a>14.2.3 混合授权<a aria-hidden="true" tabindex="-1" class="hash-link" href="#1423-混合授权" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">// JWT 和 Cookies 同时授权</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">services.AddJwt(options =&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">      options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">})</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, b =&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">       b.LoginPath = &quot;/Home/Login&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">});</span></div></div></div></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="143-高级自定义授权"></a>14.3 高级自定义授权<a aria-hidden="true" tabindex="-1" class="hash-link" href="#143-高级自定义授权" title="Direct link to heading">#</a></h2><p><code>Fur</code> 框架提供了非常灵活的高级策略鉴权和授权方式，通过该策略授权方式可以实现任何自定义授权。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="1431-appauthorizehandler"></a>14.3.1 <code>AppAuthorizeHandler</code><a aria-hidden="true" tabindex="-1" class="hash-link" href="#1431-appauthorizehandler" title="Direct link to heading">#</a></h3><p><code>Fur</code> 框架提供了 <code>AppAuthorizeHandler</code> 策略授权处理程序提供基类，只需要创建自己的 <code>Handler</code> 继承它节可。如：<code>JwtHandler</code>：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.Authorization;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.Core;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Authorization;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Http;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.IdentityModel.JsonWebTokens;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Web.Core</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    /// &lt;summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    /// JWT 授权自定义处理程序</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    /// &lt;/summary&gt;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class JwtHandler : AppAuthorizeHandler</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// 请求管道</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;/summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;context&quot;&gt;&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;httpContext&quot;&gt;&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;returns&gt;&lt;/returns&gt;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public override bool Pipeline(AuthorizationHandlerContext context, DefaultHttpContext httpContext)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            var isValid = context.ValidateJwtBearer(httpContext, out JsonWebToken token);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (!isValid) return false;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            // 检查权限</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return CheckAuthorzie(httpContext);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// 检查权限</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;/summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;httpContext&quot;&gt;&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;returns&gt;&lt;/returns&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        private static bool CheckAuthorzie(DefaultHttpContext httpContext)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            // 获取权限特性</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            var securityDefineAttribute = httpContext.GetMetadata&lt;SecurityDefineAttribute&gt;();</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (securityDefineAttribute == null) return true;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return App.GetService&lt;IAuthorizationManager&gt;().CheckSecurity(securityDefineAttribute.ResourceId);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>之后注册 <code>JwtHandler</code> 即可：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">services.AddJwt&lt;JwtHandler&gt;();</span></div></div></div></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="144-授权特性及全局授权"></a>14.4 授权特性及全局授权<a aria-hidden="true" tabindex="-1" class="hash-link" href="#144-授权特性及全局授权" title="Direct link to heading">#</a></h2><p>默认情况下，所有的路由都是允许匿名访问的，所以如果需要对某个 <code>Action</code> 或 <code>Controller</code> 设定授权访问，只需要在 <code>Action</code> 或 <code>Controller</code> 贴 <code>[AppAuthorize]</code> 或 <code>[Authorize]</code> 特性即可。</p><p>如果需要对特定的 <code>Action</code> 或 <code>Controller</code> 允许匿名访问，则贴 <code>[AllowAnonymous]</code> 即可。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="1441-全局授权"></a>14.4.1 全局授权<a aria-hidden="true" tabindex="-1" class="hash-link" href="#1441-全局授权" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">services.AddJwt&lt;JwtHandler&gt;(enableGlobalAuthorize:true);</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="1442-匿名访问"></a>14.4.2 匿名访问<a aria-hidden="true" tabindex="-1" class="hash-link" href="#1442-匿名访问" title="Direct link to heading">#</a></h3><p>如果需要对特定的 <code>Action</code> 或 <code>Controller</code> 允许匿名访问，则贴 <code>[AllowAnonymous]</code> 即可。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="145-反馈与建议"></a>14.5 反馈与建议<a aria-hidden="true" tabindex="-1" class="hash-link" href="#145-反馈与建议" title="Direct link to heading">#</a></h2><div class="admonition admonition-note alert alert--secondary"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>与我们交流</h5></div><div class="admonition-content"><p>给 Fur 提 <a href="https://gitee.com/monksoul/Fur/issues/new?issue" target="_blank" rel="noopener noreferrer">Issue</a>。</p></div></div><hr><div class="admonition admonition-note alert alert--secondary"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>了解更多</h5></div><div class="admonition-content"><p>想了解更多 <code>鉴权授权</code> 知识可查阅 <a href="https://docs.microsoft.com/zh-cn/aspnet/core/security/?view=aspnetcore-5.0" target="_blank" rel="noopener noreferrer">ASP.NET Core - 安全和标识</a> 章节。</p></div></div></div></article><div class="margin-vert--xl"><div class="row"><div class="col"><a href="https://gitee.com/monksoul/Fur/tree/main/handbook/docs/auth-control.mdx" target="_blank" rel="noreferrer noopener"><svg fill="currentColor" height="1.2em" width="1.2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 40 40" style="margin-right:0.3em;vertical-align:sub"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div></div></div><div class="margin-vert--lg"><nav class="pagination-nav" aria-label="Blog list page navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/docs/cache"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« 13. 分布式缓存</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/docs/cors"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">15. CORS 跨域 »</div></a></div></nav></div></div></div><div class="col col--3"><div class="tableOfContents_3SO_"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#141-什么是鉴权" class="table-of-contents__link">14.1 什么是鉴权</a><ul><li><a href="#1411-常见的鉴权方式" class="table-of-contents__link">14.1.1 常见的鉴权方式</a></li></ul></li><li><a href="#142-如何使用" class="table-of-contents__link">14.2 如何使用</a><ul><li><a href="#1421-添加-cookie-授权" class="table-of-contents__link">14.2.1 添加 <code>Cookie</code> 授权</a></li><li><a href="#1422-添加-jwt-授权" class="table-of-contents__link">14.2.2 添加 <code>Jwt</code> 授权</a></li><li><a href="#1423-混合授权" class="table-of-contents__link">14.2.3 混合授权</a></li></ul></li><li><a href="#143-高级自定义授权" class="table-of-contents__link">14.3 高级自定义授权</a><ul><li><a href="#1431-appauthorizehandler" class="table-of-contents__link">14.3.1 <code>AppAuthorizeHandler</code></a></li></ul></li><li><a href="#144-授权特性及全局授权" class="table-of-contents__link">14.4 授权特性及全局授权</a><ul><li><a href="#1441-全局授权" class="table-of-contents__link">14.4.1 全局授权</a></li><li><a href="#1442-匿名访问" class="table-of-contents__link">14.4.2 匿名访问</a></li></ul></li><li><a href="#145-反馈与建议" class="table-of-contents__link">14.5 反馈与建议</a></li></ul></div></div></div></div></main></div></div><footer class="footer footer--dark"><div class="container"><div class="row footer__links"><div class="col footer__col"><h4 class="footer__title">文档</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/docs/get-start">入门</a></li><li class="footer__item"><a class="footer__link-item" href="/docs">指南</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">社区</h4><ul class="footer__items"><li class="footer__item"><a href="https://gitee.com/monksoul/Fur/issues" target="_blank" rel="noopener noreferrer" class="footer__link-item">讨论</a></li><li class="footer__item"><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="footer__link-item">看板</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">更多</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/blog">博客</a></li><li class="footer__item"><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="footer__link-item">仓库</a></li></ul></div></div><div class="text--center"><div>Copyright © 2020 Fur, Baiqian Co.,Ltd.</div></div></div></footer></div>
<script src="/styles.8352e18a.js"></script>
<script src="/runtime~main.98e14d7d.js"></script>
<script src="/main.04e1b7d6.js"></script>
<script src="/1.72c59440.js"></script>
<script src="/2.a2e0b0a9.js"></script>
<script src="/3.054f69af.js"></script>
<script src="/1be78505.da78ff7d.js"></script>
<script src="/85.0018927c.js"></script>
<script src="/f976f453.e1be0e0e.js"></script>
<script src="/17896441.9aece880.js"></script>
<script src="/904cf40b.dd7b9495.js"></script>
</body>
</html>